﻿#ifndef CLS_WGTBASETREEWIDGET_H
#define CLS_WGTBASETREEWIDGET_H

#include <QTreeWidget>
#include "CLS_TreeItem.hpp"
#include <QEvent>
#include "CLS_WgtTreeWidgetItem.h"
#include <QStackedWidget>

/**
枚举名称 : n_TreeExpandType
描述 : 节点展开类型
**/
typedef enum{
    n_TreeExpandType_Hide = 0,    //折叠
    n_TreeExpandType_Current,     //展开当前节点
    n_TreeExpandType_All          //展开当前节点和全部子节点
} n_TreeExpandType;

/**
枚举名称 : n_TreeItemUserType
描述 : 树节点自定义控件类型，是默认还是自定义取值要大于QTreeWidgetItem::UserType = 1000
**/
typedef enum{
    n_TreeItemUserType_User = 1001,
} n_TreeItemUserType;

/**
枚举名称 : n_ItemBtnShowType
描述 : 按钮显示方式
**/
typedef enum {
    n_ItemBtnShowType_AlwaysShow = 0, //一直显示
    n_ItemBtnShowType_EnterShow,      //鼠标移入显示
} n_ItemBtnShowType;

/**
类名称 : CLS_WgtTreeWidget
功能 : 树控件实现类
备注 :
典型用法:
**/

class CLS_WgtToolBtnStack : public QStackedWidget
{
protected:
    /**
    函 数 名：  leaveEvent
    功能描述：  离开事件
    输入参数：  _pEvent:事件
    输出参数：
    返 回 值：
    其   它：
    **/
    void leaveEvent(QEvent *_pEvent) override
    {
        this->setCurrentIndex(0);
        QStackedWidget::leaveEvent(_pEvent);
    }
};

class CLS_WgtItemToolBar;
class CLS_WgtBaseTreeWidget : public QTreeWidget
{
    Q_OBJECT
public:
    /**
    函 数 名：  CLS_WgtBaseTreeWidget
    功能描述：  构造函数
    输入参数：  _pParent:父控件 _blChecked:是否带复选框，默认带 _blDrag:是否可拖拽， 默认不可拖拽，_blDrop:是否可拖放，默认不可拖放， _blRightMenu:是否带右键菜单，默认不带，_iBtnShowType:树节点显示方式，默认鼠标滑过显示
    输出参数：
    返 回 值：
    其   它：
    **/
    explicit CLS_WgtBaseTreeWidget(QWidget *_pParent = nullptr, bool _blChecked = false, bool _blDrag = false, bool _blDrop = false, bool _blRightMenu = true, n_ItemBtnShowType _iBtnShowType = n_ItemBtnShowType_EnterShow);

    /**
    函 数 名：  ~CLS_WgtBaseTreeWidget()
    功能描述：  析构函数
    输入参数：
    输出参数：
    返 回 值：
    其   它：
    **/
    virtual ~CLS_WgtBaseTreeWidget() override;

    /**
    函 数 名：  SetLang
    功能描述：  设置语言
    输入参数：  _qstrLang：语言字符串
    输出参数：
    返 回 值：
    其   它：
    **/
    void SetLang(const QString &_qstrLang);

    /**
    函 数 名：  LoadStyleSheet
    功能描述：  设置样式
    输入参数：  _qstrStyle：样式字符串
    输出参数：
    返 回 值：
    其   它：
    **/
    void LoadStyleSheet(const QString &_qstrStyle);

    /**
    函 数 名：  Init
    功能描述：  初始化
    输入参数：  _qstrRootId : 根节点ID，_qmapTreeItems : 树信息， _blRootNodeVisible：是否构造显示根节点
    输出参数：
    返 回 值：  0：成功 -1：失败
    其   它：
    **/
    int Init(const QString &_qstrRootId, const QMap<QString, CLS_TreeItem> &_qmapTreeItems, bool _blRootNodeVisible = true);

    /**
    函 数 名：  GetItemById
    功能描述：  按id查询节点信息
    输入参数：  _qstrId : 节点id
    输出参数：  _clsItem:返回的节点信息
    返 回 值：  0：成功 -1：失败
    其   它：
    **/
    int GetItemById(const QString &_qstrId, CLS_TreeItem &_clsItem);

    /**
    函 数 名：  GetItemByName
    功能描述：  按名称查询节点信息
    输入参数：  _qstrName : 节点名称
    输出参数：  _qvecItems:返回的节点队列
    返 回 值： 0：成功 -1：失败
    其   它：
    **/
    int GetItemByName(const QString &_qstrName, QVector<CLS_TreeItem> &_qvecItems);

    /**
    函 数 名：  GetCurrentItem
    功能描述：  获取当前选中的节点
    输入参数：
    输出参数：  _clsItem:节点信息
    返 回 值： 0：成功 -1：失败
    其   它：
    **/
    int GetCurrentItem(CLS_TreeItem &_clsItem);

    /**
    函 数 名：  GetAllItems
    功能描述：  获取全部节点信息
    输入参数：
    输出参数：  _qmapTreeItems : 树信息
    返 回 值：  0：成功 -1：失败
    其   它：
    **/
    int GetAllItems(QMap<QString, CLS_TreeItem> &_qmapTreeItems);

    /**
    函 数 名：  GetCheckedItems
    功能描述：  获取选中复选框节点队列
    输入参数：  _blOnlyLeafNode：是否仅处理叶子节点，默认处理所有勾选的节点
    输出参数：  _qvecItems:选中队列
    返 回 值：  0：成功 -1：失败
    其   它：
    **/
    int GetCheckedItems(QVector<CLS_TreeItem> &_qvecItems, bool _blOnlyLeafNode = false);

    /**
    函 数 名：  GetCheckedNodes
    功能描述：  获取选中复选框的叶子节点队列
    输入参数：   _qvecItems:选中队列
    输出参数：   0：成功 -1：失败
    返 回 值：
    其   它：
    **/
    int GetCheckedNodes(QVector<CLS_TreeItem> &_qvecItems);

    /**
    函 数 名：  SortByNo
    功能描述：  排序函数
    输入参数：  _item1：比较元素1， _item2：比较元素2
    输出参数：
    返 回 值： 比较结果，true：1比2小 false：1比2大
    其   它：
    **/
    static bool SortByNo(CLS_TreeItem &_item1, CLS_TreeItem &_item2);

    /**
    函 数 名：  Clear
    功能描述：  清空数据和界面
    输入参数：
    输出参数：
    返 回 值：
    其   它：
    **/
    void Clear();

    /**
    函 数 名：  GetChilds
    功能描述：  获得所有子节点
    输入参数：  _qstrId：树Id， _blRecursive：是否递归处理，默认非递归
    输出参数：  _qvecChilds：子节点
    返 回 值： 成功：0 失败：其他值
    其   它：
    **/
    int GetChilds(const QString &_qstrId, QVector<CLS_TreeItem> &_qvecChilds, bool _blRecursive = false);

    /**
    函 数 名：  GetParent
    功能描述：  获得父节点
    输入参数：  _qstrId：树Id
    输出参数：  _parentItem：父节点
    返 回 值： 成功：0 失败：其他值
    其   它：
    **/
    int GetParent(const QString &_qstrId, CLS_TreeItem &_parentItem);

    /**
    函 数 名：  GetItemCheckStatus
    功能描述：  获得节点勾选状态
    输入参数：  _qstrId：树Id _iState：勾选状态
    输出参数：
    返 回 值： 成功：0 失败：其他值
    其   它：
    **/
    int GetItemCheckStatus(const QString &_qstrId, Qt::CheckState &_iState);

    /**
    函 数 名：  SetTextMaxWidth
    功能描述：  设置树节点文本最大宽度
    输入参数：  _iMaxLength:宽度
    输出参数：  
    返 回 值：
    其   它：
    **/
    void SetTextMaxWidth(int _iMaxLength);
protected:
    /**
    函 数 名：  mousePressEvent
    功能描述：  鼠标点击事件
    输入参数：  _pEvent:事件
    输出参数：
    返 回 值：
    其   它：
    **/
    void mousePressEvent(QMouseEvent *_pEvent) override;

    /**
    函 数 名：  mouseReleaseEvent
    功能描述：  鼠标释放事件
    输入参数：  _pEvent:事件
    输出参数：
    返 回 值：
    其   它：
    **/
    void mouseReleaseEvent(QMouseEvent *_pEvent) override;

    /**
    函 数 名：  mouseMoveEvent
    功能描述：  鼠标移动事件
    输入参数：  _pEvent:事件
    输出参数：
    返 回 值：
    其   它：
    **/
    void mouseMoveEvent(QMouseEvent *_pEvent) override;
    /**
    函 数 名：  dragEnterEvent
    功能描述：  拖拽进入事件
    输入参数：  _pEvent:事件
    输出参数：
    返 回 值：
    其   它：
    **/
    void dragEnterEvent(QDragEnterEvent *_pEvent) override;

    /**
    函 数 名：  dropEvent
    功能描述：  拖拽完成事件
    输入参数：  _pEvent:事件
    输出参数：
    返 回 值：
    其   它：
    **/
    void dropEvent(QDropEvent *_pEvent) override;

    /**
    函 数 名：  startDrag
    功能描述：  拖拽开始事件
    输入参数：  _qActionList: 支持的拖拽事件方式：执行拷贝还是移动
    输出参数：
    返 回 值：
    其   它：
    **/
    void startDrag(Qt::DropActions _qActionList) override;

    /**
    函 数 名：  leaveEvent
    功能描述：  离开事件
    输入参数：  _pEvent:事件
    输出参数：
    返 回 值：
    其   它：
    **/
    void leaveEvent(QEvent *_pEvent) override;

private:
    /**
    函 数 名：  CreateNode
    功能描述：  构建树节点
    输入参数：  _clsItem:节点信息
    输出参数：
    返 回 值：  树节点控件
    其   它：
    **/
    QTreeWidgetItem *CreateNode(const CLS_TreeItem &_clsItem);

    /**
    函 数 名：  CreateItemButtons
    功能描述：  构建button列表
    输入参数：  _qstrId:节点Id _vecItemButtons:button列表信息
    输出参数：
    返 回 值：  toolbar控件
    其   它：
    **/
    CLS_WgtItemToolBar *CreateItemButtons(const QString &_qstrId, const QVector<CLS_ItemButton> &_vecItemButtons);

    /**
    函 数 名：  CreateTree
    功能描述：  构建树控件
    输入参数：  _pParent：父节点， _clsTreeItem：节点信息，_qmapChildren：子节点信息， _qmapTreeItems：树信息 ，_blCreate：是否构建根节点：默认构建
    输出参数：
    返 回 值：  0：成功 -1：失败
    其   它：
    **/
    int CreateTree(QTreeWidgetItem *_pParent, const CLS_TreeItem &_clsTreeItem, const QMap<QString, QVector<CLS_TreeItem>> &_qmapChildren, bool _blCreate = true);

    /**
    函 数 名：  GetChildNode
    功能描述：  获得指定节点下的子节点
    输入参数：  _pItem：节点， _blRecursive：是否递归处理，默认非递归
    输出参数：  _vecChildNodes：子节点队列
    返 回 值：  0：成功 -1：失败
    其   它：
    **/
    int GetChildNode(QTreeWidgetItem* _pItem, QVector<QTreeWidgetItem*> &_vecChildNodes, bool _blRecursive = false);

    /**
    函 数 名：  GetParentNode
    功能描述：  获得指定节点的父节点，递归获得
    输入参数：  _pItem：节点
    输出参数：  _vecParentNodes：组织结构上的所有父节点队列
    返 回 值：  0：成功 -1：失败
    其   它：
    **/
    int GetParentNode(QTreeWidgetItem* _pItem, QVector<QTreeWidgetItem*> &_vecParentNodes);

    /**
    函 数 名：  GetParentNode
    功能描述：  获得指定节点的父节点，递归获得
    输入参数：  _pItem：节点
    输出参数：  _qmapParentNodes：所有父节点
    返 回 值：  0：成功 -1：失败
    其   它：
    **/
    int GetParentNode(QTreeWidgetItem* _pItem, QMap<QString, QTreeWidgetItem*> &_qmapParentNodes);

    /**
    函 数 名：  GetNodeByName
    功能描述：  通过名称获得对应的节点
    输入参数：  _qstrName：名称
    输出参数：  _qmapItems：查找到的所有节点
    返 回 值：  0：成功 -1：失败
    其   它：
    **/
    int GetNodeByName(const QString &_qstrName, QMap<QString, QTreeWidgetItem*> &_qmapItems);

    /**
    函 数 名：  GetNodeById
    功能描述：  通过id获得树节点控件
    输入参数：  _qstrId：节点id
    输出参数：
    返 回 值：  树节点控件
    其   它：
    **/
    QTreeWidgetItem* GetNodeById(const QString &_qstrId);

    /**
    函 数 名：  GetBindData
    功能描述：  通过树控件拿绑定数据
    输入参数：  _pItem：树控件
    输出参数：  _clsItem：节点信息
    返 回 值：   0：成功 -1：失败
    其   它：
    **/
    int GetBindData(QTreeWidgetItem* _pItem, CLS_TreeItem &_clsItem);

public slots:
    /**
    函 数 名：  AddItem
    功能描述：  添加节点
    输入参数：   _clsTreeItem : 节点信息
    输出参数：
    返 回 值：
    其   它：
    **/
    void AddItem(const CLS_TreeItem &_clsTreeItem);

    /**
    函 数 名：  AddItems
    功能描述：  节点信息
    输入参数：   _qvecTreeItems : 节点信息队列
    输出参数：
    返 回 值：
    其   它：
    **/
    void AddItems(const QVector<CLS_TreeItem> &_qvecTreeItems);

	void AddItems(const QString &_qstrParentId, const QVector<CLS_TreeItem> &_qvecTreeItems);

    /**
    函 数 名：  DeleteItem
    功能描述：  删除节点
    输入参数：   _strId:节点id
    输出参数：
    返 回 值：
    其   它：
    **/
    void DeleteItem(const QString &_qstrId);

    /**
    函 数 名：  UpdateItem
    功能描述：  更新节点
    输入参数：   _clsItem:节点信息
    输出参数：   0：查询成功 -1：查询失败
    返 回 值：
    其   它：
    **/
    void UpdateItem(const CLS_TreeItem &_clsItem);

    /**
    函 数 名：  UpdateItemIcon
    功能描述：  更新节点图标
    输入参数：   _qstrId:节点信息 _qstrIcon：图标信息
    输出参数：   0：查询成功 -1：查询失败
    返 回 值：
    其   它：
    **/
    void UpdateItemIcon(const QString &_qstrId, const QString &_qstrIcon);

    /**
    函 数 名：  SetCurrentItem
    功能描述：  设置当前选中的节点
    输入参数：   _qstrId:节点id _blSend:true-发信号 false-不发信号
    输出参数：
    返 回 值：
    其   它：
    **/
    void SetCurrentItem(const QString _qstrId, bool _blSend = false);

    /**
    函 数 名：  SetItemCheckStatus
    功能描述：  设置复选框状态
    输入参数：   _qstrId:节点id _iState:选中状态 _blSend:true-发信号 false-不发信号
    输出参数：   0：查询成功 -1：查询失败
    返 回 值：
    其   它：
    **/
    void SetItemCheckStatus(const QString &_qstrId, Qt::CheckState _iState, bool _blSend = false);

    /**
    函 数 名：  设置节点展开状态
    功能描述：  SetItemExpandStatus
    输入参数：   _qstrId : 节点Id _iExpandType：展开方式
    输出参数：
    返 回 值：
    其   它：
    **/
    void SetItemExpandStatus(const QString &_qstrId, n_TreeExpandType _iExpandType);

    /**
    函 数 名：  SetAllExpandStatus
    功能描述：  设置展开所有节点
    输入参数：   _blShow : true-展开全部节点 false-折叠全部节点
    输出参数：
    返 回 值：
    其   它：
    **/
    void SetAllExpandStatus(bool _blShow);

    /**
    函 数 名：  SetShowItemById
    功能描述：  按id模糊过滤显示树列表
    输入参数：   _qstrId : 节点Id
    输出参数：
    返 回 值：
    其   它：
    **/
    void SetShowItemById(const QString &_qstrId);

    /**
    函 数 名：  SetShowItemByName
    功能描述：  按名称模糊过滤树列表
    输入参数：   _qstrName : 节点名称
    输出参数：
    返 回 值：
    其   它：
    **/
    void SetShowItemByName(const QString &_qstrName);

    /**
    函 数 名：  MoveUpOneRow
    功能描述：  上移一行
    输入参数：  _qstrSrcId：源节点Id _qstrDesId：目的节点Id
    输出参数：  无
    返 回 值：  0：成功 <0：失败
    其   它：
    **/
    int MoveUpOneRow(const QString &_qstrSrcId, const QString &_qstrDesId);

    /**
    函 数 名：  MoveDownOneRow
    功能描述：  下移一行
    输入参数：  _qstrSrcId：源节点Id _qstrDesId：目的节点Id
    输出参数：  无
    返 回 值：  0：成功 <0：失败
    其   它：
    **/
    int MoveDownOneRow(const QString &_qstrSrcId, const QString &_qstrDesId);

protected slots:
    /**
    函 数 名：  SlotClickButton
    功能描述：  按钮单击处理
    输入参数：  _qstrId:节点ID, _clsBtn:button信息
    输出参数：
    返 回 值：
    其   它：
    **/
    void SlotClickButton(QString _qstrId, CLS_ItemButton _clsBtn);

    /**
    函 数 名：  SlotClicked
    功能描述：  节点单击处理
    输入参数：  _pItem:节点 _iColumn:列号
    输出参数：
    返 回 值：
    其   它：
    **/
    void SlotClicked(QTreeWidgetItem *_pItem, int _iColumn);

    /**
    函 数 名：  SlotDblClicked
    功能描述：  节点双击处理
    输入参数：  _pItem:节点 _iColumn:列号
    输出参数：
    返 回 值：
    其   它：
    **/
    void SlotDblClicked(QTreeWidgetItem *_pItem, int _iColumn);

    /**
    函 数 名：  SlotCheckStateChanged
    功能描述：  节点勾选改变处理
    输入参数：  _pItem:节点 _blChecked:是否勾选
    输出参数：
    返 回 值：
    其   它：
    **/
    void SlotCheckStateChanged(QTreeWidgetItem *_pItem, bool _blChecked);

    /**
    函 数 名：  SlotCurrentChanged
    功能描述：  节点改变处理
    输入参数：  _pCurrent:当前被选中节点 _pPrevious:前一个被选中节点
    输出参数：
    返 回 值：
    其   它：
    **/
    void SlotCurrentChanged(QTreeWidgetItem *_pCurrent, QTreeWidgetItem *_pPrevious);

	void SlotExpandedChanged(QTreeWidgetItem *_pCurrent);
signals:
    /**
    函 数 名：  SignClickButton
    功能描述：  单击按钮
    输入参数：   _qstrId : 节点的id _clsData:button数据
    输出参数：
    返 回 值：
    其   它：
    **/
    void SignClickButton(QString _qstrId, CLS_ItemButton _clsData);

    /**
    函 数 名：  SignClicked
    功能描述：  节点单击
    输入参数：  _qstrId:节点Id _clsData:节点数据
    输出参数：
    返 回 值：
    其   它：
    **/
    void SignClicked(QString _qstrId, CLS_TreeItem _clsData);

    /**
    函 数 名：  SignDblClicked
    功能描述：  节点双击
    输入参数：  _qstrId:节点Id _clsData:节点数据
    输出参数：
    返 回 值：
    其   它：
    **/
    void SignDblClicked(QString _qstrId, CLS_TreeItem _clsData);

    /**
    函 数 名：  SignRightClicked
    功能描述：  节点右键
    输入参数：  _qstrId:节点Id _clsData:节点数据
    输出参数：
    返 回 值：
    其   它：
    **/
    void SignRightClicked(QString _qstrId, CLS_TreeItem _clsData);

    /**
    函 数 名：  SignSelected
    功能描述：  节点选中
    输入参数：   _qstrId:节点Id _clsData:节点数据 _qstrOldId:之前选中节点Id
    输出参数：
    返 回 值：
    其   它：
    **/
    void SignSelected(QString _qstrId, CLS_TreeItem _clsData, QString _qstrOldId);

	void SignExpanded(QString _qstrId, CLS_TreeItem _clsData);
    /**
    函 数 名：  SignChecked
    功能描述：  节点勾选
    输入参数：  _qstrId:节点Id _blChecked:是否勾选 _clsData:节点数据
    输出参数：
    返 回 值：
    其   它：
    **/
    void SignChecked(QString _qstrId, bool _blChecked, CLS_TreeItem _clsData);

    /**
    函 数 名：  SignCheckedStatusChanged
    功能描述：  节点勾选状态改变
    输入参数：  _qstrId:节点Id _blChecked:是否勾选 _clsData:节点数据
    输出参数：
    返 回 值：
    其   它：
    **/
    void SignCheckedStatusChanged(QString _qstrId, bool _blChecked, CLS_TreeItem _clsData);

    /**
    函 数 名：  SignDroped
    功能描述：  节点拖放信号
    输入参数：  _clsDragItem:拖拽起始节点 _clsDropItem:拖放最终节点
    输出参数：
    返 回 值：
    其   它：
    **/
    void SignDroped(CLS_TreeItem _clsDragItem, CLS_TreeItem _clsDropItem);

private:
    /** 功能: m_qmapItems - 树节点信息 **/
    QMap<QString, QTreeWidgetItem*> m_qmapItems;

    /** 功能: m_qmapButtons - 按钮信息 **/
    QMap<QTreeWidgetItem*, CLS_WgtItemToolBar*> m_qmapButtons;

    /** 功能: m_iItemFlag - 默认标志 **/
    Qt::ItemFlags m_iItemFlag = Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsAutoTristate;

    /** 功能: m_blCheckEnable - 是否支持复选框 **/
    bool m_blCheckEnable = false;

    /** 功能: m_blDragEnable - 是否支持拖拽 **/
    bool m_blDragEnable = true;

    /** 功能: m_blDragEnable - 是否支持拖放 **/
    bool m_blDropEnable = false;

    /** 功能: m_iBtnShowType - 按钮显示方式 **/
    n_ItemBtnShowType m_iBtnShowType =n_ItemBtnShowType_EnterShow;

    /** 功能: m_pLastItem - 上一次鼠标焦点所在的item **/
    QTreeWidgetItem* m_pLastItem = nullptr;

    /** 功能: m_blCustomChecked - 是否用户勾选 **/
    bool m_blCustomChecked = true;

    /** 功能: m_blCustomSelected - 是否用户选中 **/
    bool m_blCustomSelected = true;

    /** 功能: m_blRightMenuEnable - 是否带右键菜单 **/
    bool m_blRightMenuEnable = false;
	
    /** 功能: m_clsDragBeginItem - 拖拽起始节点 **/
    CLS_TreeItem m_clsDragBeginItem;

    /** 功能: m_blDraging - 正在拖拽标志 **/
    bool m_blDraging = false;

    /** 功能: m_iMaxLength - 设置文本最大长度 **/
    int m_iMaxLength = -1;

    /** 功能: m_qstrRootId - 根节点ID **/
	QString m_qstrRootId = "";
};

#endif // CLS_WGTBASETREEWIDGET_H
